package com.weic.easycache.task;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.sql.SQLException;
import java.util.HashMap;

import org.apache.http.client.ClientProtocolException;
import org.apache.http.conn.ConnectTimeoutException;
import org.json.JSONException;
import org.xmlpull.v1.XmlPullParserException;

import com.umeng.analytics.MobclickAgent;
import com.weic.easycache.exception.ApiErrorException;
import com.weic.easycache.exception.ApiStatusException;
import com.weic.easycache.exception.FileCreateFailureException;
import com.weic.easycache.exception.HttpStatusException;
import com.weic.easycache.exception.ParamLackedException;
import com.weic.easycache.exception.SdCardNotMountedException;
import com.weic.easycache.framework.Config;
import com.weic.easycache.framework.Errors;
import com.weic.easycache.framework.UserHelper;
import com.weic.easycache.framework.biz.IBiz;
import com.weic.easycache.framework.web.ApiStatus;
import com.weic.easycache.phone.Device;
import com.weic.easycache.phone.Network;
import com.weic.easycache.task.TaskQueue.Task;
import com.weic.easycache.umeng.UMeng;
import com.weic.easycache.user.User;

import android.content.Context;
import android.text.TextUtils;

public abstract class AbsTask extends Task {
	protected final Context mContext;
	protected final IBiz<?> mBiz;
	protected final boolean mCanIrgnore;
	public AbsTask(Context context, int id, IBiz<?> biz, boolean canIrgnore) {
		super(id);
		mContext = context;
		mBiz = biz;
		mCanIrgnore = canIrgnore;
	}

	@Override
	protected final void run() {
		executeTaskAndHandlerException();
	}

	protected abstract boolean doSomething() throws Exception;

	private void executeTaskAndHandlerException() {
		try {
			setMessage(mBiz.getMessage(mId), null, null);
			if(doSomething()) {
				success();
			}else {
				failure(!mCanIrgnore);
			}
			return;
		} catch (ConnectTimeoutException e) {
			setMessage(null, null, e.getLocalizedMessage());
			setErrorCode(Errors.NET_TIMEOUT, ERROR_NO);
			MobclickAgent.onEvent(mContext, UMeng.event.id.exception_net, getErrorMsg(e));
			MobclickAgent.onEvent(mContext, UMeng.event.id.user_net_info, getNetInfo(e));
			e.printStackTrace();
		} catch (SocketTimeoutException e) {
			setMessage(null, null, e.getLocalizedMessage());
			setErrorCode(Errors.NET_TIMEOUT, ERROR_NO);
			MobclickAgent.onEvent(mContext, UMeng.event.id.exception_net, getErrorMsg(e));
			MobclickAgent.onEvent(mContext, UMeng.event.id.user_net_info, getNetInfo(e));
			e.printStackTrace();
		} catch (HttpStatusException e) {
			setMessage(null, null, e.getMessage());
			setErrorCode(Errors.HTTP_STATUS, e.getCode());
			MobclickAgent.onEvent(mContext, UMeng.event.id.exception_net, getErrorMsg(e));
			MobclickAgent.onEvent(mContext, UMeng.event.id.user_net_info, getNetInfo(e));
			e.printStackTrace();
		} catch (UnknownHostException e) {
			setErrorCode(Errors.NET_NO_HOST, ERROR_NO);
			MobclickAgent.onEvent(mContext, UMeng.event.id.exception_net, getErrorMsg(e));
			MobclickAgent.onEvent(mContext, UMeng.event.id.user_net_info, getNetInfo(e));
			e.printStackTrace();
		} catch (ApiStatusException e) {
			setMessage(null, null, e.getMessage());
			if(ApiStatus.isUserInvalid(e.getCode())) {
				setErrorCode(Errors.NEED_LOGIN, e.getCode());
			}else {
				setErrorCode(Errors.API_STATUS, e.getCode());
				MobclickAgent.onEvent(mContext, UMeng.event.id.exception_res, getErrorMsg(e));
			}
			e.printStackTrace();
		} catch (ApiErrorException e) {
			setMessage(null, null, e.getLocalizedMessage());
			setErrorCode(Errors.API_ERROR, ERROR_NO);
			MobclickAgent.onEvent(mContext, UMeng.event.id.exception_net, getErrorMsg(e));
			MobclickAgent.onEvent(mContext, UMeng.event.id.user_net_info, getNetInfo(e));
			e.printStackTrace();

		} catch (ClientProtocolException e) {
			setMessage(null, null, e.getLocalizedMessage());
			setErrorCode(501, 1);
			MobclickAgent.onEvent(mContext, UMeng.event.id.exception_net, getErrorMsg(e));
			MobclickAgent.onEvent(mContext, UMeng.event.id.user_net_info, getNetInfo(e));
			e.printStackTrace();
		} catch (XmlPullParserException e) {
			setMessage(null, null, e.getLocalizedMessage());
			setErrorCode(502, 1);
			MobclickAgent.onEvent(mContext, UMeng.event.id.exception_res, getErrorMsg(e));
			e.printStackTrace();
		} catch (JSONException e) {
			setMessage(null, null, e.getLocalizedMessage());
			setErrorCode(503, 1);
			MobclickAgent.onEvent(mContext, UMeng.event.id.exception_res, getErrorMsg(e));
			e.printStackTrace();

		} catch (FileNotFoundException e) {
			setMessage(null, null, e.getLocalizedMessage());
			setErrorCode(504, 1);
			MobclickAgent.onEvent(mContext, UMeng.event.id.exception_file, getErrorMsg(e));
			e.printStackTrace();
		} catch (FileCreateFailureException e) {
			setMessage(null, null, e.getLocalizedMessage());
			setErrorCode(504, 2);
			MobclickAgent.onEvent(mContext, UMeng.event.id.exception_file, getErrorMsg(e));
			e.printStackTrace();
		} catch (SdCardNotMountedException e) {
			setMessage(null, null, e.getLocalizedMessage());
			setErrorCode(504, 3);
			MobclickAgent.onEvent(mContext, UMeng.event.id.exception_file, getErrorMsg(e));
			e.printStackTrace();

		} catch (IOException e) {
			setMessage(null, null, e.getLocalizedMessage());
			setErrorCode(505, 1);
			MobclickAgent.onEvent(mContext, UMeng.event.id.exception_data_def, getErrorMsg(e));
			e.printStackTrace();
		} catch (SQLException e) {
			setMessage(null, null, e.getLocalizedMessage());
			setErrorCode(506, 1);
			MobclickAgent.onEvent(mContext, UMeng.event.id.exception_db, getErrorMsg(e));
			e.printStackTrace();
		} catch (android.database.SQLException e) {
			setMessage(null, null, e.getLocalizedMessage());
			setErrorCode(506, 2);
			MobclickAgent.onEvent(mContext, UMeng.event.id.exception_db, getErrorMsg(e));
			e.printStackTrace();
		} catch (ParamLackedException e) {
			if(!mCanIrgnore) {
				setMessage(null, null, e.getLocalizedMessage());
				setErrorCode(Errors.PARAM_LACKED, ERROR_NO);
				MobclickAgent.onEvent(mContext, UMeng.event.id.exception_data_def, getErrorMsg(e));
			}
			e.printStackTrace();
		} catch (RuntimeException e) {
			throw e;	//为防止错误，这里不要拦截

		} catch (Exception e) {
			setMessage(null, null, e.getLocalizedMessage());
			setErrorCode(507, 1);
			MobclickAgent.onEvent(mContext, UMeng.event.id.exception_data_def, getErrorMsg(e));
			e.printStackTrace();
		}
		failure(!mCanIrgnore);
	}

	private HashMap<String, String> getErrorMsg(Exception e) {
		//map至多传10个参数
		HashMap<String, String> map = new HashMap<String, String>();

		String excepName = e.getClass().getName();
		excepName = excepName.substring(excepName.lastIndexOf('.') + 1);
		User user = getUser();
		String label = (user!=null ? user.name + "--" : "") + excepName + (TextUtils.isEmpty(e.getLocalizedMessage()) ?
				"" : ('_' + e.getLocalizedMessage().trim().replaceAll("[\\. \":]+", "_")));
		if(label.length() > 100) label = label.substring(0, 100);
		map.put(UMeng.event.key.exception_user, getUserAndDevice());
		map.put(UMeng.event.key.exception_msg, label);

		StackTraceElement[] stackTraces = e.getStackTrace();
		if(stackTraces!=null && stackTraces.length>0) {
			StackTraceElement elem;
			int j = 0;
			for(int i=0; i<stackTraces.length; i++) {
				elem = stackTraces[i];
				label = elem.getClassName();
				if(i > 2 && label.indexOf("Task") < 0) continue;

				label = label.substring(label.lastIndexOf('.') + 1);

				map.put(UMeng.event.key.exception_class_method_line + j++,
						excepName + "--" + label + '_' + elem.getMethodName() + '_' + elem.getLineNumber());
				if(map.size() >= 9) break;
			}
		}
		return map;
	}

	private HashMap<String, String> getNetInfo(Exception e) {
		//map至多传10个参数
		HashMap<String, String> map = new HashMap<String, String>();

		String excepName = e.getClass().getName();
		excepName = excepName.substring(excepName.lastIndexOf('.') + 1);
		User user = getUser();
		String userName = user!=null ? user.name + "--" : "";
		String label = userName + excepName + (TextUtils.isEmpty(e.getLocalizedMessage()) ?
				"" : ('_' + e.getLocalizedMessage().trim().replaceAll("[\\. \":]+", "_")));
		if(label.length() > 100) label = label.substring(0, 100);
		map.put(UMeng.event.key.net_info_user, getUserAndDevice());
		map.put(UMeng.event.key.net_info_msg, label);
		String host = ;
		map.put(UMeng.event.key.net_info_ip, userName + "hostip_" + Network.IP_Host(host, true) + "-userip_" + Network.IP_Me(true) +
				"--host-" + host.replace('.', '_'));
		map.put(UMeng.event.key.net_info_dns, userName + "dns1_" + Network.DNS(1, true) + "-dns2_" + Network.DNS(2, true));
		map.put(UMeng.event.key.net_info_ping, userName + Network.PING(host, true));
		return map;
	}

	private String getUserAndDevice() {
		Device device = Device.getInstance(mContext);
		User user = getUser();

		String result = ((user!=null ? (user.name+"-") : "")+
				"v"+Config.get().versionName+'-'+
				device.sysVersion+'-'+
				device.brand.replace(' ', '_')+'-'+
				Network.getConnectedNetworkType(mContext).type).trim().replace('.', '_').replace(" ", "");
		return result;
	}

	protected User getUser() {
		return UserHelper.getUser();
	}

	protected boolean isNetConnected() {
		return Network.isNetConnected(mContext);
	}
}
